#include "timingWheel.h"
//遍历链表
int forEcahSet(set_t* pset){
    setNode_t* pCur = pset->Head;
    printf("forEachSet pset= %p:\n",pset);
    while(pCur!=NULL){
        printf("%d\n",pCur->netfd);
        pCur = pCur->next;
    }
    printf("\n");
    return 0;
}

//取出链表的第一个元素,并将该元素从链表删除
int deSet(set_t* pset,int* netfd){
    setNode_t* pNode = pset->Head;
    *netfd = pNode->netfd;
    pset->Head = pNode->next;
    free(pNode);
    return 0;
}
//将netfd加入集合
int enSet(set_t *pset,int netfd){
    /* forEcahSet(pset); */
    setNode_t* pCur = pset->Head;
    while(pCur){
        //集合中本来就有该netfd
        if(pCur->netfd == netfd){
            return 0;
        }
        pCur = pCur->next;
    }
    //集合中没有该netfd,使用头插法插入该节点
    setNode_t* pNew = (setNode_t*)calloc(1,sizeof(setNode_t));
    pNew->netfd = netfd;
    pNew->next = pset->Head;
    pset->Head = pNew;
    return 0;
}
//将netfd从集合中删除
int deNetfd(set_t* pset,int netfd){
    if(pset->Head ==NULL){
        return 0;
    }
    //集合不为空
    if(pset->Head->netfd == netfd){
        //netfd位于链表头,删除
        free(pset->Head);
        pset->Head = NULL;
        return 0;
    }
    //netfd不在链表头
    setNode_t* pPre = pset->Head;
    setNode_t* pCur = pset->Head;
    if(pPre->next!=NULL){
        pCur = pCur->next;
    }
    while(pCur){
        //在集合中找到netfd所在的节点
        if(pCur->netfd == netfd){
            break;
        }
        pCur = pCur->next;
        pPre = pPre->next;
    }
    if(pCur == NULL){
        //netfd所在的节点不在此集合中
        return -1;
    }
    //找到netfd所在的集合为pCur;
    //删除节点
    pPre->next = pCur->next;
    free(pCur);
    return 0;
}

//初始化队列
int loopQueueInit(loopQueue_t* pQueue,int queueSize){
    pQueue->queueSize = queueSize;
    pQueue->Queue = (set_t**)calloc(queueSize,sizeof(set_t*));  //pQueue->Queue是一个二级指针(指向set_t*的数组)
    //pQueue->Queue[idx] 是一个一级指针
    /* printf("pQueue->Queue = %p\n",pQueue->Queue); */
    for(int idx =0;idx <queueSize;++idx){
        //初始化每个一级指针
        pQueue->Queue[idx] = (set_t*)calloc(1,sizeof(set_t));
        pQueue->Queue[idx]->Head = NULL;
        /* printf("pQueue->Queue[%d] = %p\n",idx,pQueue->Queue[idx]); */
    }
    return 0;
}

//销毁队列
int loopQueueDestory(loopQueue_t* pQueue){
    for(int idx =0;idx <pQueue->queueSize;++idx){
        //释放每个一级指针
        free(pQueue->Queue[idx]);
    }
    free(pQueue->Queue);
    return 0;
}

//找出当前踢出链接的链表
int findSet(const loopQueue_t* pQueue,int idx,set_t* pset){
    pset = pQueue->Queue[idx];
    return 0;
}

//初始化timeoutShare_t
int timeoutShareInit(timeoutShare_t* pTimeoutShare,int queueSize){
    loopQueueInit(&(pTimeoutShare->loopQueue),queueSize);
    for(int idx = 0;idx <1024 ; ++idx){
        pTimeoutShare->fdToIdx[idx] = -1;
    }
    pTimeoutShare->Idx = 0;
    return 0;
}

//设置当前要处理的集合所在队列中的位置
int setTimeoutIdx(timeoutShare_t* pTimeoutShare,int idx){
    pTimeoutShare->Idx = idx;
    return 0;
}

//-----------------timeoutShare_t的核心操作 ---------
//1.清空队列中指定下标集合
int emptySet(timeoutShare_t* pTimeoutShare,cmdShare_t* netfdToPcmd[],int idx){
    set_t *pset = pTimeoutShare->loopQueue.Queue[idx];
    /* forEcahSet(pset); */
    while(pset->Head!=NULL){
        int netfd = -1;
        deSet(pset,&netfd);
        /* printf("emptySet pset = %p netfd = %d\n",pset,netfd); */
        if(netfd != -1){
            if(netfdToPcmd[netfd]==NULL){
                printf("netfd = %d timeout! disconnected\n",netfd);
            }else{
                printf("netfd = %d,username = %s timeout! disconnected\n",netfd,netfdToPcmd[netfd]->username);
                free(netfdToPcmd[netfd]);
                netfdToPcmd[netfd] = NULL;
            }
            pTimeoutShare->fdToIdx[netfd] = -1;
            close(netfd);
        }
    }
    return 0;
}

//2.将netfd加入集合
int joinSet(timeoutShare_t* pTimeoutShare,int netfd){
    set_t* pset = pTimeoutShare->loopQueue.Queue[pTimeoutShare->Idx];
    pTimeoutShare->fdToIdx[netfd] = pTimeoutShare->Idx;
    /* printf("joinSet pset = %p\n",pset); */
    /* forEcahSet(pset); */ 
    int ret = enSet(pset,netfd);    
    /* forEcahSet(pset); */ 
    return ret;
}

//3.从集合中删除指定的netfd
int delNetfd(timeoutShare_t* pTimeoutShare,int netfd){
    //找到对应的集合
    int idx = pTimeoutShare->fdToIdx[netfd];
    set_t* pset = pTimeoutShare->loopQueue.Queue[idx];
    /* printf("delNetfd:"); */
    /* forEcahSet(pset); */
    int ret = deNetfd(pset,netfd);
    /* printf("delNetfd:"); */
    /* forEcahSet(pset); */
    return ret;
}
